#include "app_buffer.h"
#include "log/log.h"
#include <string.h>
#include <stdlib.h>

static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;

Buffer *app_buffer_init(int size)
{
    // 检查参数的合法性
    if (size <= 0)
    {
        log_error("size must be greater than 0");
        return NULL;
    }

    // 初始化buffer结构体空间
    Buffer *buffer = malloc(sizeof(Buffer));
    if (buffer == NULL)
    {
        log_error("malloc buffer failed");
        return NULL;
    }

    // 初始化buffer的ptr属性
    buffer->ptr = malloc(size);
    if (buffer->ptr == NULL)
    {
        log_error("malloc buffer->ptr failed");
        free(buffer);
        return NULL;
    }

    // 初始化buffer的其它属性
    buffer->total_size = size;
    buffer->len = 0;
    buffer->offset = 0;

    // 初始化buffer的lock
    buffer->lock = init_lock;
    return buffer;
}

void app_buffer_free(Buffer *buffer)
{
    // 检查参数的合法性
    if (buffer == NULL)
    {
        log_error("buffer is NULL");
        return;
    }
    // 由内向外释放内存
    if (buffer->ptr != NULL)
    {
        free(buffer->ptr);
    }

    pthread_mutex_destroy(&buffer->lock);

    free(buffer);
}

int app_buffer_write(Buffer *buffer, char *data, int len)
{
    // 检查参数的合法性
    if (buffer == NULL || data == NULL || len <= 0)
    {
        log_error("invalid parameters");
        return -1;
    }
    // 检查buffer是否还有足够的空间
    if (buffer->len + len > buffer->total_size)
    {
        log_error("buffer is full");
        return -1;
    }
    pthread_mutex_lock(&buffer->lock);
    // 计算写入buffer的起始位置
    int write_start = buffer->offset + buffer->len;
    // 修正写入的起始位置
    if (write_start >= buffer->total_size)
    {
        write_start -= buffer->total_size;
    }

    //  将数据写入buffer
    if (write_start + len <= buffer->total_size) // 一次写入
    {
        memcpy(buffer->ptr + write_start, data, len);
    }
    else // 两次写入
    {
        int len1 = buffer->total_size - write_start;
        memcpy(buffer->ptr + write_start, data, len1);
        memcpy(buffer->ptr, data + len1, len - len1);
    }

    pthread_mutex_unlock(&buffer->lock);

    // 更新buffer的len属性
    buffer->len += len;

    log_debug("buffer write success, len = %d,buffer offset = %d, len=%d,ptr=%s",
              len, buffer->offset, buffer->len, buffer->ptr);

    return 0;
}

int app_buffer_read(Buffer *buffer, char *data, int len)
{
    // 检查参数的合法性
    if (buffer == NULL || data == NULL || len <= 0)
    {
        log_error("invalid parameters");
        return -1;
    }
    // 检查buffer中是否有足够的数据
    if (buffer->len < len)
    {
        log_error("buffer is not enough data");
        return -1;
    }

    pthread_mutex_lock(&buffer->lock);

    // 将数据从buffer中读取出来
    if (buffer->offset + len <= buffer->total_size) // 一次读取
    {
        memcpy(data, buffer->ptr + buffer->offset, len);
        // 更新buffer的offset属性
        buffer->offset += len;
    }
    else // 两次读取
    {
        // 计算第一段的长度
        int len1 = buffer->total_size - buffer->offset;
        memcpy(data, buffer->ptr + buffer->offset, len1);
        memcpy(data + len1, buffer->ptr, len - len1);
        // 更新buffer的offset属性
        buffer->offset = len - len1;
    }
    // 更新buffer的len属性
    buffer->len -= len;

    pthread_mutex_unlock(&buffer->lock);

    log_debug("buffer read success, len = %d,buffer offset = %d, len=%d,ptr=%s",
              len, buffer->offset, buffer->len, buffer->ptr);
    return 0;
}
